StoryboardのContainer ViewでUINavigationControllerを埋め込む
Container View
iOS6からStoryboardでContainer Viewが利用できるようになりました。Container Viewは、ViewControllerに子ViewControllerを追加するchildViewControllerの仕組みをStoryboardで扱えるようにするものです。
Container ViewでNavigationControllerを埋め込む
Container ViewはUIViewControllerを子ViewControllerとして追加します。したがって、UIViewControllerのサブクラスであるUINavigationControllerも子ViewControllerとして追加できます。こうすると、ナビゲーションで画面遷移をしても常に特定の領域が表示される状態を、コードを書かずにStoryboardだけで表現することができます。
実行すると以下のようになります。iPhoneでは、iAdで広告を入れたい場合などに便利そうです。以前からコードを書くことで実現できていたことではありますが、Storyboardを使って簡単に定義できるようになったのは嬉しいです。
Container Viewの使い方
せっかくなので、Container Viewの使い方についても簡単にまとめます。
適当なプロジェクトを作成してStoryboardを用意します。Storyboardのファイルを開いたら、キャンバスにViewControllerを追加します。次に、Xcode右下のObject libraryからContainer Viewを選択して、追加したViewControllerにドロップします。
すると、ドロップ先のViewControllerに"Container"と表示されたグレーの領域ができ、同時にセグエで接続された新しいViewControllerが追加されます。これで、新しく追加されたViewControllerはContainer ViewをドロップしたViewControllerの子ViewControllerとなり、"Container"と表示された領域に子ViewControllerのviewが表示されるようになります。
"Container"と表示された領域をキャンバス上でリサイズすると、対応する子ViewControllerのサイズも同じサイズに変更されます。また、複数のContainer Viewで複数のViewControllerを埋め込むこともできます。
実行すると以下のようになります。
なお、Container Viewという名前のUIコンポーネントのクラスは存在しません。Container Viewを配置した領域には、実際にはUIViewがサブビューとして配置され、そのUIViewのサブビューとして子ViewControllerのviewが追加されるようになっています。
EmbedSegueを編集する
Container Viewの追加時に一緒に追加されるセグエは、埋め込むViewControllerを指定するためのEmbedSegueというセグエです。埋め込むViewControllerを変えたい場合や、既にStoryboardのキャンバス上にあるViewControllerを埋め込みたい場合は、このEmbedSegueを繋ぎ直すことで対応できます。
試しに、先ほど埋め込んだ子ViewControllerをTableViewControllerに差し替えてみます。まず、EmbedSegueを選択して削除します。
TableViewControllerを追加します。
TableViewControllerを選択し、Connections inspectorのEmbedをContainer Viewに接続します。もしくは、Container Viewを選択してConnections inspectorのviewDidLoadをTableViewControllerに接続してもOKです。
これでTableViewControllerを埋め込むことができました。
タブレットにおけるViewControllerの分割
特に画面領域の広いiPadでは、ViewControllerを分割することによって下記のメリットが期待できます。
- ビューに対する操作ロジックの肥大化の防止
- ビュー要素間の責務の混在の防止
- ビューの再利用がしやすくなる
上記メリットを得るためには、子ViewController外のビュー要素にまたがる処理は全て親ViewControllerにデリゲートすることがポイントです。子ViewController同士で参照しあったりすると、ViewControllerを分割した意味がなくなり、実装の手間を増やすだけの結果になってしまいます。